package com.gun.management.module.task.service.taskRewardRecord;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.gun.management.framework.common.exception.ServiceException;
import com.gun.management.framework.common.pojo.PageResult;
import com.gun.management.framework.common.util.object.BeanUtils;
import com.gun.management.framework.mybatis.core.util.MyBatisUtils;
import com.gun.management.module.member.api.point.MemberPointApi;
import com.gun.management.module.member.enums.point.MemberPointBizTypeEnum;
import com.gun.management.module.task.controller.admin.taskRewardRecord.vo.TaskRewardRecordPageReqVO;
import com.gun.management.module.task.controller.admin.taskRewardRecord.vo.TaskRewardRecordRespVO;
import com.gun.management.module.task.controller.admin.taskRewardRecord.vo.TaskRewardRecordSaveReqVO;
import com.gun.management.module.task.controller.app.vo.AppTaskAuditInfoRespVO;
import com.gun.management.module.task.controller.app.vo.AppTaskRewardRecordSaveReqVO;
import com.gun.management.module.task.dal.dataobject.taskInfo.TaskInfoDO;
import com.gun.management.module.task.dal.dataobject.taskRewardLog.TaskRewardLogDO;
import com.gun.management.module.task.dal.dataobject.taskRewardRecord.TaskRewardRecordDO;
import com.gun.management.module.task.dal.mysql.taskInfo.TaskInfoMapper;
import com.gun.management.module.task.dal.mysql.taskRewardLog.TaskRewardLogMapper;
import com.gun.management.module.task.dal.mysql.taskRewardRecord.TaskRewardRecordMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import jakarta.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

import static com.gun.management.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.gun.management.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
import static com.gun.management.module.task.enums.ErrorCodeConstants.*;

/**
 * 任务奖励记录信息 Service 实现类
 *
 * @author 测试账号
 */
@Service
@Validated
public class TaskRewardRecordServiceImpl implements TaskRewardRecordService {
    @Resource
    private TaskInfoMapper taskInfoMapper;
    @Resource
    private TaskRewardRecordMapper rewardRecordMapper;


    @Resource
    private TaskRewardLogMapper rewardLogMapper;

    @Resource
    private MemberPointApi memberPointApi;


    @Override
    public Long createRewardRecord(TaskRewardRecordSaveReqVO createReqVO) {
        // 插入
        TaskRewardRecordDO rewardRecord = BeanUtils.toBean(createReqVO, TaskRewardRecordDO.class);

        // 校验每天做任务数量是否每天的上限和总上限
        verifyTaskRecord("create",createReqVO.getTaskId(),getLoginUserId());

        rewardRecordMapper.insert(rewardRecord);


        // 返回
        return rewardRecord.getId();
    }

    @Override
    @Transactional(rollbackFor = {Throwable.class, ServiceException.class})
    public void updateRewardRecord(TaskRewardRecordSaveReqVO updateReqVO) {
        // 校验存在
        verifyRewardRecord(updateReqVO.getId());

        TaskInfoDO taskInfoDO = taskInfoMapper.selectById(updateReqVO.getTaskId());
        if (taskInfoDO == null) {
            throw new ServiceException(401,String.format("id为%d对应的任务%s信息不存在!",updateReqVO.getTaskId()));
        }
        if (taskInfoDO.getStatus() == 1) {
            throw new ServiceException(401,String.format("%s已经禁用，不能提交审核!",taskInfoDO.getName()));
        }

        // 更新
        TaskRewardRecordDO updateObj = BeanUtils.toBean(updateReqVO, TaskRewardRecordDO.class);
        if (updateReqVO.getAuditStatus() == 0) {
            throw new ServiceException(517,"请选择审核状态");
        }

        TaskRewardRecordDO taskRewardRecordDO = rewardRecordMapper.selectById(updateReqVO.getId());
        if (taskRewardRecordDO == null) {
            throw new ServiceException(401,"当前记录不存在，无法执行更新操作！");
        }

        updateObj.setTaskId(taskRewardRecordDO.getTaskId());
        updateObj.setRewardScore(taskRewardRecordDO.getRewardScore());
        updateObj.setUserId(taskRewardRecordDO.getUserId());
        updateObj.setAuditStatus(updateReqVO.getAuditStatus());
        if (updateReqVO.getAuditStatus() == 1) { // 如果是成功,则给用户添加积分

            TaskRewardLogDO taskRewardLogDO = new TaskRewardLogDO();
            taskRewardLogDO.setTaskId(updateObj.getTaskId());
            taskRewardLogDO.setUserId(updateObj.getUserId());
            taskRewardLogDO.setRewardScore(updateObj.getRewardScore());
            taskRewardLogDO.setTaskScreenshot(updateObj.getTaskScreenshot());
            taskRewardLogDO.setRewardTime(updateObj.getRewardTime());
            taskRewardLogDO.setDayRewardTimes(taskInfoDO.getDayRewardTimes());
            taskRewardLogDO.setMaxRewardTimes(taskInfoDO.getMaxRewardTimes());
            taskRewardLogDO.setCreateTime(updateObj.getCreateTime());
            taskRewardLogDO.setCreator(updateObj.getCreator());
            taskRewardLogDO.setUpdateTime(updateObj.getUpdateTime());
            taskRewardLogDO.setUpdater(updateObj.getUpdater());

            rewardLogMapper.insertAndGetId(taskRewardLogDO);

             // 添加到会员积分记录表
            if (taskInfoDO.getCategoryId() == 1) { // 如果是邀请新用户
                memberPointApi.addPoint(updateObj.getUserId(),updateObj.getRewardScore(), MemberPointBizTypeEnum.INVITE_NEWUSER_POINT.getType(), String.valueOf(taskRewardLogDO.getId()));
            }
            if (taskInfoDO.getCategoryId() == 2) { // 如果是应用市场评价
                memberPointApi.addPoint(updateObj.getUserId(), updateObj.getRewardScore(), MemberPointBizTypeEnum.APP_REVIEW_TASK.getType(), String.valueOf(taskRewardLogDO.getId()));
            }
            if (taskInfoDO.getCategoryId() == 3) { // 如果是参与活动
                memberPointApi.addPoint(updateObj.getUserId(), updateObj.getRewardScore(), MemberPointBizTypeEnum.JOIN_ACTIVITY_TASK.getType(), String.valueOf(taskRewardLogDO.getId()));
            }
            if (taskInfoDO.getCategoryId() == 4) { // 如果是分享微信好友
                memberPointApi.addPoint(updateObj.getUserId(), updateObj.getRewardScore(), MemberPointBizTypeEnum.SHARE_WEIXIN_TASK.getType(), String.valueOf(taskRewardLogDO.getId()));
            }
            if (taskInfoDO.getCategoryId() == 5) { // 如果是分享朋友圈
                memberPointApi.addPoint(updateObj.getUserId(), updateObj.getRewardScore(), MemberPointBizTypeEnum.SHARE_FRIEND_TASK.getType(), String.valueOf(taskRewardLogDO.getId()));
            }

            updateObj.setAuditUserId(getLoginUserId());  // 更新审核人
            updateObj.setAuditTime(LocalDateTime.now()); // 更新审核时间


            verifyTaskRecord("update",updateObj.getTaskId(),getLoginUserId());
        }

        if (updateReqVO.getAuditStatus() == 2) { // 如果是失败
            if (StringUtils.isBlank(updateReqVO.getAuditReason())) {
                throw new ServiceException(408,"拒绝原因不能为空!");
            }

          // 设置成待审核状态，相当于打回去给前端用户，让他再提交一次。
            updateObj.setAuditUserId(getLoginUserId());  // 更新审核人
            updateObj.setAuditTime(LocalDateTime.now()); // 更新审核时间
        }

        rewardRecordMapper.updateById(updateObj);

        if (updateReqVO.getAuditStatus() == 2) {
            updateObj.setAuditStatus(0); // 设置成待审核状态，相当于打回去给前端用户，让他再提交一次。

            updateObj.setTaskScreenshot(updateReqVO.getTaskScreenshot());
            updateObj.setCreateTime(LocalDateTime.now());
            updateObj.setCreator(String.valueOf(getLoginUserId()));
            updateObj.setAuditUserId(null);  // 更新审核人
            updateObj.setAuditTime(null); // 更新审核时间
            updateObj.setAuditReason(null);
            updateObj.setId(null);

        }

    }


    @Override
    @Transactional(rollbackFor = {Throwable.class, ServiceException.class})
    public void updateAppRewardRecord(AppTaskRewardRecordSaveReqVO appTaskRewardRecordSaveReqVO) {
        // 校验存在
//        verifyRewardRecord(appTaskRewardRecordSaveReqVO.getId());
        // 更新
        TaskRewardRecordDO updateObj = BeanUtils.toBean(appTaskRewardRecordSaveReqVO, TaskRewardRecordDO.class);
//        if (appTaskRewardRecordSaveReqVO.getAuditStatus() == 0) {
//            throw new ServiceException(517,"请选择审核状态");
//        }
        TaskInfoDO taskInfoDO = taskInfoMapper.selectById(appTaskRewardRecordSaveReqVO.getTaskId());
        if (taskInfoDO == null) {
            throw new ServiceException(401,String.format("id为%d对应的任务信息不存在,不允许提交审核!",appTaskRewardRecordSaveReqVO.getTaskId()));
        }
        if (taskInfoDO.getStatus() == 1) {
            throw new ServiceException(402,String.format("%s已经禁用，不允许提交审核!",taskInfoDO.getName()));
        }
        if (taskInfoDO.getCategoryId() != 2) { // 应用评价类任务
            throw new ServiceException(403,String.format("%s为非应用评价类任务，不允许提交审核!",taskInfoDO.getName()));
        }
        // 开始时间：当天开始
        LocalDateTime startOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        LocalDateTime endOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);

        LambdaQueryWrapper<TaskRewardRecordDO> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(TaskRewardRecordDO::getTaskId,appTaskRewardRecordSaveReqVO.getTaskId());
        lambdaQueryWrapper.eq(TaskRewardRecordDO::getUserId,getLoginUserId());
        lambdaQueryWrapper.eq(TaskRewardRecordDO::getAuditStatus, 0);
        lambdaQueryWrapper.orderByDesc(TaskRewardRecordDO::getId);
        lambdaQueryWrapper.last("LIMIT 1");

        TaskRewardRecordDO taskRewardRecordDO = rewardRecordMapper.selectOne(lambdaQueryWrapper);
        if (taskRewardRecordDO != null) {
                throw new ServiceException(401,"当前已有审核中的截图，不能重复提交！");
        }  else {

            updateObj.setTaskId(appTaskRewardRecordSaveReqVO.getTaskId());
            updateObj.setUserId(getLoginUserId());
            updateObj.setTaskScreenshot(appTaskRewardRecordSaveReqVO.getTaskScreenshot());
            updateObj.setRewardScore(taskInfoDO.getRewardScore());
            updateObj.setAuditStatus(0);

            verifyTaskRecord("create",updateObj.getTaskId(),getLoginUserId());
            rewardRecordMapper.insert(updateObj);
        }
    }


    @Override
    public void deleteRewardRecord(Long id) {
        // 校验存在
        validateRewardRecordExists(id);
        // 删除
        rewardRecordMapper.deleteById(id);
    }

    private void validateRewardRecordExists(Long id) {
        if (rewardRecordMapper.selectById(id) == null) {
            throw exception(TASK_REWARD_RECORD_NOT_EXISTS);
        };
    }

    private void verifyRewardRecord(Long id) {

        TaskRewardRecordDO taskRewardRecordDO =  rewardRecordMapper.selectById(id);
        if (rewardRecordMapper.selectById(id) == null) {
            throw exception(TASK_REWARD_RECORD_NOT_EXISTS);
        };
        if (taskRewardRecordDO.getAuditStatus() == 1) {
            throw exception(TASK_REWARD_RECORD_AUDIT_HAS_APPROVED);
        }
        if (taskRewardRecordDO.getAuditStatus() == 2) {
            throw exception(TASK_REWARD_RECORD_AUDIT_HAS_REFUSED);
        }
    }

    @Override
    public TaskRewardRecordDO getRewardRecord(Long id) {
        return rewardRecordMapper.selectById(id);
    }

    @Override
    public TaskRewardRecordRespVO getTaskRewardRecordById(Long id) {
        return rewardRecordMapper.getTaskRewardRecordById(id);
    }

    @Override
    public PageResult<TaskRewardRecordRespVO> getRewardRecordPage(TaskRewardRecordPageReqVO pageReqVO) {

        IPage<TaskRewardRecordRespVO> pageResult = rewardRecordMapper.selectTaskRewardRecordPageList(MyBatisUtils.buildPage(pageReqVO), pageReqVO.getTaskName(), pageReqVO.getCategoryId(),pageReqVO.getAuditStatus(),pageReqVO.getRewardTime(),pageReqVO.getUserName());
        return new PageResult<>(pageResult.getRecords(), pageResult.getTotal());
    }


    /**
     * 根据任务taskId来获取用审核状态信息
     * @param taskId
     * @return
     */
    public AppTaskAuditInfoRespVO getAuditStatus(Long taskId) {
        if (taskId == null) throw new ServiceException(401,"任务id不能为空");
        AppTaskAuditInfoRespVO appTaskAuditInfoRespVO = rewardRecordMapper.getTaskAuditInfoById(taskId);
        if (StringUtils.isBlank(appTaskAuditInfoRespVO.getTaskScreenshot())) {
            appTaskAuditInfoRespVO.setAuditStatus(3);  // 图片未上传
        }

        return appTaskAuditInfoRespVO;
    }

    /**
     * 校验添加或者更新记录的合法性
     * @param type
     * @param taskId
     * @param userId
     */
    private void verifyTaskRecord(String type,long taskId,long userId) {
        // 没有根据每天奖励次数 和  总次数 做校验 。同一个人同一个任务。接口可以提交2条 进来
        LocalDateTime startOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        LocalDateTime endOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
        LocalDateTime[] createTime = new LocalDateTime[]{
                startOfDay,endOfDay
        };
       int dayAddRewardTimes = rewardRecordMapper.getTaskRecords(taskId,userId,createTime);
       TaskInfoDO taskInfoDO = taskInfoMapper.selectById(taskId);

       if (taskInfoDO == null) {
           throw new ServiceException(401, String.format("编号为%d的任务信息不存在，可能已经删除",taskId));
       }

        if (taskInfoDO.getDayRewardTimes() <= dayAddRewardTimes) {
            throw new ServiceException(470, String.format("用户做任务数量不允许超过每天奖励限制数量%d",taskInfoDO.getDayRewardTimes()));
        }

       int  totalRewardTimes = rewardRecordMapper.getTaskRecords(taskId,userId,null);

       if (taskInfoDO.getMaxRewardTimes() <= totalRewardTimes) {
           throw new ServiceException(470, String.format("用户做任务数量不允许超过奖励限制数量%d",taskInfoDO.getMaxRewardTimes()));
       }


    }
}